/* eslint-disable no-continue */
/**
 * 计算两个数字的和
 * 1. 注意遍历的数组的越界问题.
 * 2. 排序后可以方便的剪枝.
 *    1. 剩下的最小的组合的值
 * 3. 排序后两个的排序使用中间夹窗口的方式获取.
 * 4. **排序后不重复的选择元素就可以保证选择的结果不重复**.
 */
function fourSum(nums: number[], target: number): number[][] {
  const result: number[][] = []
  const len = nums.length
  nums.sort((a, b) => a - b)
  for (let i = 0; i < len - 3; i++) {
    if (i > 0 && nums[i] === nums[i - 1]) continue
    if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break
    for (let j = i + 1; j < len - 2; j++) {
      if (j > i + 1 && nums[j] === nums[j - 1]) continue
      if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break
      for (let m = j + 1; m < len - 1; m++) {
        if (m > j + 1 && nums[m] === nums[m - 1]) continue
        if (nums[i] + nums[j] + nums[m] + nums[m + 1] > target) break
        for (let n = m + 1; n < len; n++) {
          if (n > m + 1 && nums[n] === nums[n - 1]) continue
          if (nums[i] + nums[j] + nums[m] + nums[n] > target) break
          const s = nums[i] + nums[j] + nums[m] + nums[n]
          if (s === target) {
            result.push([nums[i], nums[j], nums[m], nums[n]])
          } else if (s > target) {
            break
          }
        }
      }
    }
  }
  return result
}

export { fourSum }
